package common.netty.server;

import common.RpcRequest;
import common.RpcResponse;
import common.netty.server.codec.ServerFrameDecoder;
import common.netty.server.codec.ServerFrameEncoder;
import common.netty.server.codec.ServerProtocolDecoder;
import common.netty.server.codec.ServerProtocolEncoder;
import common.netty.server.handle.ServerProcessHandler;
import common.netty.server.handle.ServerIdleCheckHandler;
import common.serializer.impl.JSONSerializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioChannelOption;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.concurrent.DefaultThreadFactory;
import io.netty.util.concurrent.UnorderedThreadPoolEventExecutor;

import java.util.Map;

/**
 * @Author: Hugh
 * @Date: 2020/6/13
 */
public class NettyServerStart {

    public void startWithPort(Integer port, final Map map) throws Exception{
        ServerBootstrap serverBootstrap = new ServerBootstrap();

        serverBootstrap.channel(NioServerSocketChannel.class);
        serverBootstrap.option(NioChannelOption.SO_BACKLOG, 1024);
        serverBootstrap.childOption(NioChannelOption.TCP_NODELAY, true);
        serverBootstrap.handler(new LoggingHandler(LogLevel.INFO));
        LoggingHandler loggingHandler = new LoggingHandler(LogLevel.INFO);

        //thread
        NioEventLoopGroup bossGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("boss"));
        NioEventLoopGroup workGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("worker"));
        UnorderedThreadPoolEventExecutor businessGroup = new UnorderedThreadPoolEventExecutor(2, new DefaultThreadFactory("business"));
        serverBootstrap.group(bossGroup, workGroup);
        serverBootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {
            @Override
            protected void initChannel(NioSocketChannel ch) throws Exception {

                ChannelPipeline pipeline = ch.pipeline();
                pipeline.addLast(loggingHandler);

                pipeline.addLast("idleHandler", new ServerIdleCheckHandler());

                pipeline.addLast("frameDecoder", new ServerFrameDecoder());
                pipeline.addLast("frameEncoder", new ServerFrameEncoder());

//                pipeline.addLast("protocolDecoder", new ServerProtocolDecoder(RpcRequest.class, new JSONSerializer()));
                pipeline.addLast("protocolDecoder", new ServerProtocolDecoder());
                pipeline.addLast("protocolEncoder", new ServerProtocolEncoder());

                pipeline.addLast(businessGroup, new ServerProcessHandler(map));
            }
        });

        ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
        channelFuture.channel().closeFuture().sync();

//       finally {
//           bossGroup.shutdownGracefully();
//           workGroup.shutdownGracefully();
//           businessGroup.shutdownGracefully();
//      }
    }
}
